#include "stdafx.h"
#include "CppUnitTest.h"
#include "..\CExpressionUtil\Expression.h"
#include "..\CExpressionUtil\DependencySorter.h"

using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace std;
using namespace CExpression;

namespace CExpressionUtilUnitTest
{
	TEST_CLASS(DependencySorterUnitTest)
	{
	public:

		TEST_METHOD(CTestDependencySorter)
        {
			ExpressionString test[5][2] = 
            {
                {TEXT("a"),TEXT("b+c+d+e+f")},
                {TEXT("b"),TEXT("c+d")},
                {TEXT("c"),TEXT("2")},
                {TEXT("d"),TEXT("3")},
                {TEXT("e"),TEXT("4")}
            };
            map<ExpressionString,Expression*> dic;
            for (int i = 0; i < 5; i++)
            {
				dic.insert(make_pair(test[i][0],new Expression(test[i][1])));
            }
			DependencySorter sorter;
            vector< pair<const ExpressionString*,Expression*> > *exps = sorter.Sort(dic);
            map<ExpressionString,size_t> *sortedDic = GetResultMap(exps);
			Assert::AreEqual(5,exps->size(),0.0001);
            Assert::IsTrue((*sortedDic)[TEXT("b")] > (*sortedDic)[TEXT("c")] && (*sortedDic)[TEXT("b")] > (*sortedDic)[TEXT("d")]);
            Assert::IsTrue((*sortedDic)[TEXT("a")] > (*sortedDic)[TEXT("b")] && (*sortedDic)[TEXT("a")] > (*sortedDic)[TEXT("c")] && 
                (*sortedDic)[TEXT("a")] > (*sortedDic)[TEXT("d")] && (*sortedDic)[TEXT("a")] > (*sortedDic)[TEXT("e")]);
			Free(dic,sortedDic);
        }

        TEST_METHOD(CTestDependencySorterDirecrCross)
        {
            ExpressionString test[6][2] = 
            {
                {TEXT("a"),TEXT("b+c")},
                {TEXT("b"),TEXT("d+e")},
                {TEXT("c"),TEXT("d+10")},
                {TEXT("d"),TEXT("f+1")},
                {TEXT("e"),TEXT("4")},
                {TEXT("f"),TEXT("5")},
            };
			map<ExpressionString,Expression*> dic;
            for (int i = 0; i < 6; i++)
            {
				dic.insert(make_pair(test[i][0],new Expression(test[i][1])));
            }
			DependencySorter sorter;
            vector< pair<const ExpressionString*,Expression*> > *exps = sorter.Sort(dic);
            map<ExpressionString,size_t> *sortedDic = GetResultMap(exps);
			Assert::AreEqual(6,exps->size(),0.0001);
            Assert::IsTrue((*sortedDic)[TEXT("d")] > (*sortedDic)[TEXT("f")]);
            Assert::IsTrue((*sortedDic)[TEXT("c")] > (*sortedDic)[TEXT("d")]);
            Assert::IsTrue((*sortedDic)[TEXT("b")] > (*sortedDic)[TEXT("d")] && (*sortedDic)[TEXT("b")] > (*sortedDic)[TEXT("e")]);
            Assert::IsTrue((*sortedDic)[TEXT("a")] > (*sortedDic)[TEXT("b")] && (*sortedDic)[TEXT("a")] > (*sortedDic)[TEXT("c")]);
			Free(dic,sortedDic);
        }

        TEST_METHOD(CTestDependencySorterCross)
        {
            ExpressionString test[7][2] = 
            {
                {TEXT("a"),TEXT("b+c+d+e+f")},
                {TEXT("b"),TEXT("c+d")},
                {TEXT("c"),TEXT("2")},
                {TEXT("d"),TEXT("3")},
                {TEXT("e"),TEXT("4")},
                {TEXT("f"),TEXT("5")},
                {TEXT("wqwqw"),TEXT("b+c")}
            };
			map<ExpressionString,Expression*> dic;
            for (int i = 0; i < 7; i++)
            {
				dic.insert(make_pair(test[i][0],new Expression(test[i][1])));
            }
			DependencySorter sorter;
            vector< pair<const ExpressionString*,Expression*> > *exps = sorter.Sort(dic);
            map<ExpressionString,size_t> *sortedDic = GetResultMap(exps);
			Assert::AreEqual(7,exps->size(),0.0001);
            Assert::IsTrue((*sortedDic)[TEXT("b")] > (*sortedDic)[TEXT("c")] && (*sortedDic)[TEXT("b")] > (*sortedDic)[TEXT("d")]);
            Assert::IsTrue((*sortedDic)[TEXT("a")] > (*sortedDic)[TEXT("b")] && (*sortedDic)[TEXT("a")] > (*sortedDic)[TEXT("c")] &&
                (*sortedDic)[TEXT("a")] > (*sortedDic)[TEXT("d")] && (*sortedDic)[TEXT("a")] > (*sortedDic)[TEXT("e")] && 
				(*sortedDic)[TEXT("a")] > (*sortedDic)[TEXT("f")]);
            Assert::IsTrue((*sortedDic)[TEXT("wqwqw")] > (*sortedDic)[TEXT("b")] && (*sortedDic)[TEXT("wqwqw")] > (*sortedDic)[TEXT("c")]);
			Free(dic,sortedDic);
        }

        TEST_METHOD(CTestDependencySorterCircularReferenceUndirect)
        {
            ExpressionString test[6][2] = 
            {
                {TEXT("a"),TEXT("b+c+d+e+f")},
                {TEXT("b"),TEXT("c+d")},
                {TEXT("c"),TEXT("2")},
                {TEXT("d"),TEXT("a")},
                {TEXT("e"),TEXT("4")},
                {TEXT("f"),TEXT("5")},
            };
            map<ExpressionString,Expression*> dic;
            for (int i = 0; i < 6; i++)
            {
				dic.insert(make_pair(test[i][0],new Expression(test[i][1])));
            }
			DependencySorter sorter;
            vector< pair<const ExpressionString*,Expression*> > *exps = sorter.Sort(dic);
			Assert::AreEqual(sorter.ErrorOccured(),true);
        }

        TEST_METHOD(CTestDependencySorterCircularReferenceDirect)
        {
            ExpressionString test[6][2] = 
            {
                {TEXT("a"),TEXT("b+c+d+e+f+a")},
                {TEXT("b"),TEXT("c+d")},
                {TEXT("c"),TEXT("2")},
                {TEXT("d"),TEXT("3")},
                {TEXT("e"),TEXT("4")},
                {TEXT("f"),TEXT("5")},
            };
			map<ExpressionString,Expression*> dic;
            for (int i = 0; i < 6; i++)
            {
				dic.insert(make_pair(test[i][0],new Expression(test[i][1])));
            }
			DependencySorter sorter;
            vector< pair<const ExpressionString*,Expression*> > *exps = sorter.Sort(dic);
			Assert::AreEqual(sorter.ErrorOccured(),true);
        }
		
	private:
		map<ExpressionString,size_t>* GetResultMap(vector< pair<const ExpressionString*,Expression*> > *exps)
        {
            map<ExpressionString,size_t> *ret = new map<ExpressionString,size_t>();
            for (int i = 0; i < exps->size(); i++)
            {
				pair<const ExpressionString*,Expression*> &p=(*exps)[i];
                ret->insert(make_pair(*(p.first), i));
            }
            return ret;
        }

		void Free(map<ExpressionString,Expression*> &dic,map<ExpressionString,size_t> *sortedDic)
		{
			for(map<ExpressionString,Expression*>::iterator i=dic.begin();i!=dic.end();++i)
			{
				delete i->second;
			}
			delete sortedDic;
		}

	};
}